home *** CD-ROM | disk | FTP | other *** search
- /*==========================================================================
-
- SampleApp.c
-
- This simple application illustrates the code stripping functionality
- provided by SlimApp.
-
- It provides an "About SampleApp..." menu command to get at a dialog
- box that provides access to the code stripping features, and a simple
- command that counts to 10,000,000 to give you a feel for whether you're
- running native-68K, 68K-emulated, or PPC-native.
-
- Copyright 1995 by Blake Ward.
-
- Permission is granted for unrestricted use, provided the author
- is credited.
-
- ==========================================================================*/
-
- #include "SlimApp.h"
-
- #include <Palettes.h>
-
-
-
- /*============================================================================
- MISC STRUCTURES & CONSTANTS
- ============================================================================*/
-
-
- // Menu Resource IDs:
- #define kMenuBarID 128
-
- #define kAppleMenuID 128
- #define kAboutSampleApp 1
-
- #define kFileMenuID 129
- #define kCount 1
- #define kQuit 3
-
-
- // Simple dialog for displaying how long it took to count
- #define kCountMessageDlg 2000
-
-
- // Our sample About Box
- #define kAboutBoxDialogID 1000
- #define OK 1
- #define ABOUT_OK_OUTLINE 2
- #define ABOUT_APP_TITLE 3
- #define ABOUT_COPYRIGHT 4
- #define ABOUT_VERSION 5
- #define REDUCE_CODE_BTN 6
- #define ABOUT_CODE_TYPE 7
-
- // Dialog for warning the user before stripping the application
- #define kWarningAlertID 2001
-
-
- // SampleApp's string resources
- #define kSampleAppStrings 1000
- #define kVersionLabel 1
-
-
- /*============================================================================
- INTERNAL PROTOTYPES (Functions used only within this file)
- ============================================================================*/
-
- void main(void);
- void EventLoop(void);
- OSErr Initialize(void);
- Boolean DoMenu(long int menuChoice);
-
- void DoAboutSampleApp(void);
- void DoCountTenMillion(void);
-
-
- // User Item drawing routines for the About Box
- pascal void DrawStyledVersionString(DialogPtr dp, short itemNumber);
- pascal void DrawStyledCodeType(DialogPtr dp, short itemNumber);
-
- // Miscellaneous routines useful for dealing with dialog items
- pascal void DrawDefaultButtonOutline(DialogPtr dp, short outlineUserItemNumber);
- void SetUserItem(DialogPtr dp, short int itemNumber, UserItemUPP drawRoutine);
- void EnableDialogControl(DialogPtr dp, short itemNumber, Boolean enable);
- void RenameDialogControl(DialogPtr dp, short itemNumber, StringPtr newName);
-
-
-
-
- /*============================================================================
- main:
-
- Initializes the toolbox, installs the menus and then calls a loop to
- handle all of the events until the user quits.
-
- ============================================================================*/
- void
- main(void)
- {
-
- if (Initialize() != noErr)
- return;
-
- // Handle events until they quit
- EventLoop();
-
- }
-
-
-
- /*============================================================================
- Initialize:
-
- This function initializes the toolbox and sets up the menus.
-
- ============================================================================*/
- OSErr
- Initialize(void)
- {
-
- Handle menuBar;
-
- // Call this once before anything else to ensure we've got a fully expanded
- // heap zone.
- MaxApplZone();
-
- // We don't use much memory, so probably don't need to call this at all...
- MoreMasters();
-
- // Initialize all of the toolbox managers
- InitGraf(&qd.thePort);
- InitFonts();
- InitWindows();
- InitMenus();
- TEInit();
- InitDialogs(nil);
- InitCursor();
-
- // Install our menus (stored in SampleApp.rsrc)
- menuBar = GetNewMBar(kMenuBarID);
- if (menuBar == nil)
- return resNotFound;
-
- SetMenuBar(menuBar);
-
- // Add the DA names to the apple menu
- AppendResMenu(GetMenuHandle(kAppleMenuID), 'DRVR'); /* add DA names to Apple menu */
-
- DrawMenuBar();
-
- return noErr;
- }
-
-
-
-
- /*============================================================================
- EventLoop:
-
- This function just loops endlessly processing events until the user
- selects Quit from the File menu.
-
- Since SampleApp is an extremely limited application, we don't need to
- handle very many events here (essentially all we need to watch for is
- menu commands).
-
- ============================================================================*/
- void
- EventLoop(void)
- {
- EventRecord event;
- Boolean userQuit = false;
- WindowPtr whichWindow;
- Point where;
- short int windowCode;
-
- // Clear out left over events
- FlushEvents(everyEvent, 0);
-
- // Loop until the user 'Quit's
- while (!userQuit) {
-
- // Get the next event
- WaitNextEvent(everyEvent, &event, 30, 0L);
- switch(event.what) {
- case mouseDown: // In which window, and where??
- windowCode = FindWindow(event.where, &whichWindow);
- switch(windowCode) {
- case inSysWindow: // It's not in our windows or menus
- SystemClick(&event, whichWindow);
- break;
- case inMenuBar: // In a menu, handle the command
- userQuit = DoMenu(MenuSelect(event.where));
- break;
- }
- break; // end mouseDown
- case keyDown:
- case autoKey: // If a Command key was pressed, pass to MenuKey
- if((event.modifiers & cmdKey) != 0) {
- userQuit = DoMenu(MenuKey((char) (event.message & 0xff)));
- }
- break;
- case diskEvt: // Handle disk insertion event
- if (HiWord(event.message) != noErr) {
- DILoad();
- where.h = 112;
- where.v = 80;
- DIBadMount(where, event.message);
- DIUnload();
- }
- break;
- } // switch
- } // while (!userQuit)
- }
-
-
-
-
- /*============================================================================
- DoMenu:
-
- This function is called when the user has pulled down a menu or typed the
- command key equivalent of a menu item.
-
- ============================================================================*/
- Boolean
- DoMenu(long int menuResult)
- {
- short int menuID, menuItem;
- unsigned char name[255];
-
- // Find out which menu they selected an item from
- menuID = HiWord(menuResult);
-
- // If it's zero, then they moved the mouse off the menus without
- // selecting anything
- if (menuID == 0) {
- // This seems to be necessary if they're running "Apple Menu Options" and
- // they select a control panel from the hierarchical menu.
- HiliteMenu(0);
- return false;
- }
-
- // Which item in that menu did they select?
- menuItem = LoWord(menuResult);
-
- switch (menuID) {
- case kAppleMenuID:
- if (menuItem == kAboutSampleApp)
- DoAboutSampleApp();
- else {
- GetMenuItemText(GetMenuHandle(kAppleMenuID), menuItem, name);
- OpenDeskAcc(name);
- }
- break;
- case kFileMenuID:
- switch(menuItem) {
- case kCount:
- DoCountTenMillion();
- break;
- case kQuit:
- return true;
- }
- break;
- }
-
- HiliteMenu(0);
-
- return false;
- }
-
-
-
-
- /*============================================================================
- DoCountTenMillion:
-
- This simple routine just counts to 10,000,000 and then puts up a quick
- alert box telling the user how long it took.
-
- ============================================================================*/
- void
- DoCountTenMillion(void)
- {
- long int count;
- unsigned long int tm;
- Str63 time;
- CursHandle cursH;
-
- // Change the cursor to a watch while we count
- cursH = GetCursor(watchCursor);
- HLock((Handle)cursH);
- SetCursor(*cursH);
-
- tm = TickCount();
-
- for (count = 0; count < 10000000; count++)
- ;
-
- NumToString(TickCount() - tm, time);
-
- #if powerc
- ParamText(time, "\pPowerPC", "\p", "\p");
- #else
- ParamText(time, "\p680x0", "\p", "\p");
- #endif
-
- SetCursor(&qd.arrow);
- ReleaseResource((Handle)cursH);
-
- // Put up the alert
- NoteAlert(kCountMessageDlg, 0L);
-
- }
-
-
-
-
- /*============================================================================
- DoAboutSampleApp:
-
- The fat application stripping code is accessed from the About Box.
- This routine displays the about box dialog and handles clicking the
- "Remove Code" and "OK" buttons.
-
- Several things are illustrated in this dialog:
-
- - We dynamically set the label in the button to reflect what we're
- actually going to do. This makes the button a little big, but it's
- important since the average user is going to have trouble
- understanding the whole "fat application" concept anyway.
- - Once the unneeded code has been stripped, we hide the button since
- they can't do it again and they can't undo it.
- - We always display a message in the dialog indicating which version of
- the application they have. It's easy to forget after a few months what
- was done to the application, and this provides an easy reminder of which
- version they have. If you get calls to your customer support department,
- they can easily ask the user to bring up the About Box for a quick check
- of the application's version number and whether it's been stripped.
-
- ============================================================================*/
- void
- DoAboutSampleApp(void)
- {
- short int whichVersion;
- short int item;
- DialogPtr dp;
- UserItemUPP versionStringUPP, codeTypeUPP, outlineDefaultUPP;
- Str255 tmpStr;
-
- dp = GetNewDialog(kAboutBoxDialogID, 0L, (WindowPtr)-1L );
-
- // Set up the drawing routines for the version # and code type user items
- // To make the dialog look a little nicer, we display these using
- // styled text.
- versionStringUPP = NewUserItemProc(DrawStyledVersionString);
- SetUserItem(dp, ABOUT_VERSION, versionStringUPP);
- codeTypeUPP = NewUserItemProc(DrawStyledCodeType);
- SetUserItem(dp, ABOUT_CODE_TYPE, codeTypeUPP);
-
- // Install a user item to draw the outline around the OK button.
- outlineDefaultUPP = NewUserItemProc(DrawDefaultButtonOutline);
- SetUserItem(dp, ABOUT_OK_OUTLINE, outlineDefaultUPP);
-
- // Figure out whether we still have the 68K and PowerPC code
- whichVersion = Has68KPowerPCCode();
-
- // Set up the reduce application button:
- // - if this version isn't fat, then we can't strip anything out of the binary
- // - we want the button label to give an indication of what is about to be done
- if (!SafeToStrip())
- EnableDialogControl(dp, REDUCE_CODE_BTN, false);
- if (whichVersion != kFatBinaryApplication)
- HideDialogItem(dp, REDUCE_CODE_BTN);
- else {
- #ifdef powerc
- GetIndString(tmpStr, kSlimAppStrings, kStrip68KButtonLabel);
- #else
- GetIndString(tmpStr, kSlimAppStrings, kStripPowerPCButtonLabel);
- #endif
- RenameDialogControl(dp, REDUCE_CODE_BTN, tmpStr);
- }
-
- // Loop until they click OK, and then tear everything down and return
- while (true) {
- ModalDialog((ModalFilterUPP)0L, &item);
- switch (item) {
- case OK:
- DisposeDialog(dp);
- DisposeRoutineDescriptor(versionStringUPP);
- DisposeRoutineDescriptor(codeTypeUPP);
- DisposeRoutineDescriptor(outlineDefaultUPP);
- return;
- case REDUCE_CODE_BTN:
- #ifdef powerc
- GetIndString(tmpStr, kSlimAppStrings, kPowerMacOnlyWarning);
- #else
- GetIndString(tmpStr, kSlimAppStrings, k68KOnlyWarning);
- #endif
- ParamText(tmpStr, "\p", "\p", "\p");
- if (CautionAlert(kWarningAlertID, 0L) == 1) {
- SetPort(dp);
- if (StripFatApplication() == noErr) {
- HideDialogItem(dp, REDUCE_CODE_BTN);
- }
- else StopAlert(kCodeStripFailedErrorDialog, 0L);
- }
- // The application version message may have changed, so
- // just make sure that it completely redraws
- SetPort(dp);
- InvalRect(&dp->portRect);
- break;
- }
- }
-
- }
-
-
-
-
- /*============================================================================
- DrawStyledVersionString:
-
- This user item just retrieves the short version string from the
- application's resources and displays it centered in small bold geneva.
-
- ============================================================================*/
- pascal void
- DrawStyledVersionString(DialogPtr dp, short itemNumber)
- {
- short itemType;
- Handle item;
- Rect itemRect;
- Style txFace;
- short int txSize;
- short int txFont;
- Str63 versionLabel, versionStr;
-
- // Make sure that we're actually drawing into the dialog
- SetPort(dp);
-
- // Get all of the current values so that we can put them back when we're finished
- txFont = dp->txFont;
- txFace = dp->txFace;
- txSize = dp->txSize;
-
- // Set it up the way we want
- TextFace(bold);
- TextFont(geneva);
- TextSize(9);
-
- // Get the "Version" string and append the current short version
- // string from the 'vers' resource
- GetIndString(versionLabel, kSampleAppStrings, kVersionLabel);
- GetShortVersion(versionStr);
- BlockMoveData(&versionStr[1], &versionLabel[versionLabel[0] + 1], versionStr[0]);
- versionLabel[0] += versionStr[0];
-
- // Get the item rectangle so we know where to draw
- GetDialogItem(dp, itemNumber, &itemType, &item, &itemRect);
-
- // Draw the string
- TextBox(&versionLabel[1], versionLabel[0], &itemRect, teCenter);
-
- // Put the port back the way it was
- TextFace(txFace);
- TextFont(txFont);
- TextSize(txSize);
-
- }
-
-
-
-
- /*============================================================================
- DrawStyledCodeType:
-
- This user item just checks to see which version of the application we
- currently have and then displays the appropriate message in
- small bold geneva. If the button is visible (we have a fat version),
- then the message is centered under the button. Otherwise we draw it
- flush left in the corner of the dialog.
-
- ============================================================================*/
- pascal void
- DrawStyledCodeType(DialogPtr dp, short itemNumber)
- {
- short itemType;
- Handle item;
- Rect itemRect;
- Style txFace;
- short int txSize;
- short int txFont;
- short whichVersion;
- Str255 codeTypeStr;
-
- // Make sure that we're actually drawing into the dialog
- SetPort(dp);
-
- // Get all of the current values so that we can put them back when we're finished
- txFont = dp->txFont;
- txFace = dp->txFace;
- txSize = dp->txSize;
-
- // Set it up the way we want
- TextFace(bold);
- TextFont(geneva);
- TextSize(9);
-
- // Figure out whether we still have the 68K and PowerPC code
- whichVersion = Has68KPowerPCCode();
-
- // Build a version string to display based on the version resource
- GetIndString(codeTypeStr, kSlimAppStrings, whichVersion == k68KApplication ? k68KLabel :
- (whichVersion == kPowerPCApplication ? kPowerPCLabel : kFatBinaryLabel));
-
- // Get the item rectangle so we know where to draw
- GetDialogItem(dp, itemNumber, &itemType, &item, &itemRect);
-
- // Draw the string
- TextBox(&codeTypeStr[1], codeTypeStr[0], &itemRect,
- whichVersion == kFatBinaryApplication ? teCenter : teFlushLeft);
-
- // Put the port back the way it was
- TextFace(txFace);
- TextFont(txFont);
- TextSize(txSize);
-
- }
-
-
-
-
- /*============================================================================
- DrawDefaultButtonOutline:
-
- This procedure should be installed as the draw routine for a user item
- that overlaps the default button. It assumes that the default item is the
- item number that dialog has stored as the default (normally item #1).
-
- If the item is disabled, the outline is drawn in the gray color or a
- gray pattern.
-
- This routine is overkill for SampleApp, but you might find it useful
- elsewhere.
-
- ============================================================================*/
- pascal void
- DrawDefaultButtonOutline(DialogPtr dp, short /*outlineUserItemNumber*/)
- {
- short itemType;
- Handle item;
- Rect itemRect;
- PenState savePen;
- Boolean grayAvailable = false;
- RGBColor fore, back, gray;
-
- // Make sure we're actually drawing in the dialog
- SetPort(dp);
-
- // Save the pen state so that we can put it back when we're done
- GetPenState(&savePen);
-
- // Use whichever item the dialog thinks is the default
- GetDialogItem(dp, ((DialogPeek)dp)->aDefItem, &itemType, &item, &itemRect);
-
- // We want to draw a thick outline, so the easiest way is to just change
- //the pen thickness
- PenNormal();
- PenSize(3, 3);
- InsetRect(&itemRect, -4, -4);
-
- // Is the button currently enabled?
- if ((*(ControlHandle)item)->contrlHilite == 255) {
- GetForeColor(&fore);
- gray = fore;
- GetBackColor(&back);
- grayAvailable = GetGray(GetGDevice(), &back, &gray);
- if (grayAvailable) {
- RGBForeColor(&gray);
- }
- else PenPat(&qd.dkGray);
- }
-
- FrameRoundRect(&itemRect, 16, 16);
-
- // Put back the original color and pen state
- if (grayAvailable)
- RGBForeColor(&fore);
- SetPenState(&savePen);
-
- }
-
-
-
-
- /*============================================================================
- SetUserItem:
-
- Convenience routine for dealing with dialog box items.
- Provides a handy way to associate a UserItemUPP with a user item.
-
- ============================================================================*/
- void SetUserItem(DialogPtr dp, short int itemNumber, UserItemUPP drawRoutine)
- {
- short itemType;
- Handle item;
- Rect itemRect;
-
- GetDialogItem(dp, itemNumber, &itemType, &item, &itemRect);
- SetDialogItem(dp, itemNumber, itemType, (Handle)drawRoutine, &itemRect);
-
- }
-
-
-
-
- /*============================================================================
- EnableDialogItem:
-
- Convenience routine for dealing with dialog box items.
- Just enables/disables the given dialog control item.
-
- ============================================================================*/
- void EnableDialogControl(DialogPtr dp, short itemNumber, Boolean enableFlag)
- {
- short itemType;
- Handle item;
- Rect itemRect;
-
- GetDialogItem(dp, itemNumber, &itemType, &item, &itemRect);
-
- HiliteControl((ControlHandle)item, enableFlag ? 0 : 255);
-
- }
-
-
-
- /*============================================================================
- RenameDialogControl:
-
- Convenience routine for dealing with dialog box items.
- Just changes the title of the given dialog control (probably a button).
-
- ============================================================================*/
- void
- RenameDialogControl(DialogPtr dp, short itemNumber, StringPtr newName)
- {
- short itemType;
- Handle item;
- Rect itemRect;
-
- GetDialogItem(dp, itemNumber, &itemType, &item, &itemRect);
-
- SetControlTitle((ControlHandle)item, newName);
-
- }
-
-
-
-
-
-